{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h1> Epitope Prediction </h1>\n",
    "\n",
    "This tutorial illustrates the use of Fred2 to predict HLA-I/II epitopes and how to analyze results. Fred2 offers a long list of epitope prediction methods and was designed in such a way that extending Fred2 with your favorite method is easy.\n",
    "\n",
    "This tutorial will entail:\n",
    "- Simple epitope prediction from a list of peptide sequences and protein sequences\n",
    "- Manipulation of the results\n",
    "- Consensus prediction with multiple prediction methods\n",
    "- Integration of a new prediction method\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "<h2> Chapter 1: The basics </h2>\n",
    "<br/>\n",
    "We first start with importing the needed packages."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "%reload_ext autoreload\n",
    "%autoreload 2\n",
    "\n",
    "from Fred2.Core import Allele, Peptide, Protein,generate_peptides_from_proteins\n",
    "from Fred2.IO import read_lines, read_fasta\n",
    "from Fred2.EpitopePrediction import EpitopePredictorFactory"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Lets start of with something simple: Defining peptides, and HLA alleles. You find all basic classes under `Fred2.Core`. HLA alleles have to be defined in new nomenclature (see: <a href=\"http://hla.alleles.org/\">http://hla.alleles.org/</a>)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "peptides = [Peptide(\"SYFPEITHI\"),Peptide(\"FIASNGVKL\"), Peptide(\"LLGATCMFV\")]\n",
    "allele = Allele(\"HLA-A*02:01\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Of course we don't have to specify all peptides and alleles by hand. We can also read those from file with `read_lines`. For doing so, the file has to contain the peptide sequences and HLA alleles one per line. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "peptides2 = read_lines(\"./data/peptides.txt\", in_type=Peptide)\n",
    "alleles = read_lines(\"./data/alleles.txt\", in_type=Allele)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Proteins are a bit more complicated. They require a amino acid sequence as well as a transcript and gene ID. If `read_lines` is used generic transcript IDs are generated. Or one can use `read_fasta` to read in protein sequences in FASTA format. But one has to specify at which position of the fasta entries  the transcript ID is (based on the contained |). For example if the fasta file has the following structure\n",
    "\n",
    "\n",
    ">\\>ID_Type|Gene_ID|ID_Type|Trancsript_ID|comment<br/>\n",
    ">AAAAAAAA\n",
    "\n",
    "we would call read_fasta as follows:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[PROTEIN: MKMRFFSSPCGKAAVDPADRCKEVQQIRDQHPSK (aa-seq)\n",
      "\t\t  Protein_0 (orig transcript)\n",
      "\t\t VARIANTS:\n",
      ", PROTEIN: IPVIIERYKGEKQLPVLDKTKFLVPDHVNMSELVKI (aa-seq)\n",
      "\t\t  Protein_1 (orig transcript)\n",
      "\t\t VARIANTS:\n",
      "]\n"
     ]
    }
   ],
   "source": [
    "proteins = read_fasta(\"./data/proteins.fasta\", id_position=3, in_type=Protein)\n",
    "print proteins"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To be able to use proteins for prediction, we first have to generate k-mers of the sequences. For that we use the function `generate_peptides_from_protein`, which generates unique peptide k-mers based on the given protein sequences. These peptides are associated with the proteins from which they origin."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "peptide3 = generate_peptides_from_proteins(proteins, 9)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Fred2 has only one entry point to the different prediction methods, namely `EpitopePredictorFactory`. It handles the initialization of the different methods and also collects newly implemented prediction methods if properly implemented. To see which prediction methods Fred2 supports `EpitopePredictorFactory` can helps here as well:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "netmhc 3.0a,3.4\n",
      "smmpmbec 1.0\n",
      "syfpeithi 1.0\n",
      "netmhcpan 2.4,2.8\n",
      "netctlpan 1.1\n",
      "smm 1.0\n",
      "tepitopepan 1.0\n",
      "arb 1.0\n",
      "pickpocket 1.1\n",
      "epidemix 1.0\n",
      "netmhcii 2.2\n",
      "netmhciipan 3.0,3.1\n",
      "comblibsidney 1.0\n",
      "unitope 1.0\n",
      "hammer 1.0\n",
      "svmhc 1.0\n",
      "bimas 1.0\n"
     ]
    }
   ],
   "source": [
    "for name,version in EpitopePredictorFactory.available_methods().iteritems():\n",
    "    print name, \",\".join(version)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Lets select one and do predictions. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th>A*02:01</th>\n",
       "      <th>B*15:01</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Seq</th>\n",
       "      <th>Method</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>(A, N, G, H, D, A, K, A, K)</th>\n",
       "      <th>syfpeithi</th>\n",
       "      <td>2</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>(A, T, L, I, S, I, N, T, H)</th>\n",
       "      <th>syfpeithi</th>\n",
       "      <td>15</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>(H, I, S, L, A, N, G, H, D)</th>\n",
       "      <th>syfpeithi</th>\n",
       "      <td>8</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>(I, N, T, H, I, S, L, A, N)</th>\n",
       "      <th>syfpeithi</th>\n",
       "      <td>3</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>(I, S, I, N, T, H, I, S, L)</th>\n",
       "      <th>syfpeithi</th>\n",
       "      <td>16</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                       A*02:01  B*15:01\n",
       "Seq                         Method                     \n",
       "(A, N, G, H, D, A, K, A, K) syfpeithi        2        2\n",
       "(A, T, L, I, S, I, N, T, H) syfpeithi       15        2\n",
       "(H, I, S, L, A, N, G, H, D) syfpeithi        8        6\n",
       "(I, N, T, H, I, S, L, A, N) syfpeithi        3        3\n",
       "(I, S, I, N, T, H, I, S, L) syfpeithi       16        2"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "predictor = EpitopePredictorFactory(\"Syfpeithi\")\n",
    "results = predictor.predict(peptides2, alleles=alleles)\n",
    "results.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To initialize particular version of a prediction method, we can use the flag `version=\"\"` when calling the PredictorFactories. If we do not specify any version, Fred2 will initialize the most recent version that is supported."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th>A*02:01</th>\n",
       "      <th>B*15:01</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Seq</th>\n",
       "      <th>Method</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>(A, N, G, H, D, A, K, A, K)</th>\n",
       "      <th>syfpeithi</th>\n",
       "      <td>2</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>(A, T, L, I, S, I, N, T, H)</th>\n",
       "      <th>syfpeithi</th>\n",
       "      <td>15</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>(H, I, S, L, A, N, G, H, D)</th>\n",
       "      <th>syfpeithi</th>\n",
       "      <td>8</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>(I, N, T, H, I, S, L, A, N)</th>\n",
       "      <th>syfpeithi</th>\n",
       "      <td>3</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>(I, S, I, N, T, H, I, S, L)</th>\n",
       "      <th>syfpeithi</th>\n",
       "      <td>16</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                       A*02:01  B*15:01\n",
       "Seq                         Method                     \n",
       "(A, N, G, H, D, A, K, A, K) syfpeithi        2        2\n",
       "(A, T, L, I, S, I, N, T, H) syfpeithi       15        2\n",
       "(H, I, S, L, A, N, G, H, D) syfpeithi        8        6\n",
       "(I, N, T, H, I, S, L, A, N) syfpeithi        3        3\n",
       "(I, S, I, N, T, H, I, S, L) syfpeithi       16        2"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "predictor = EpitopePredictorFactory(\"Syfpeithi\", version=\"1.0\")\n",
    "results = predictor.predict(peptides2, alleles=alleles)\n",
    "results.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "External tools like `NetMHC` offer two additional flags when calling `.predict()`, `command=\"/path/to/binary\"` and `options=\"command options\"`. `command=\"\"` specifies the path to an alternative binary that should be used instead of the one that is globally registered. With `options=\"\"` you can specify additional commands that will directly be passed to the command line call without any sanity checks."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th>A*02:01</th>\n",
       "      <th>B*15:01</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Seq</th>\n",
       "      <th>Method</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>(A, N, G, H, D, A, K, A, K)</th>\n",
       "      <th>syfpeithi</th>\n",
       "      <td>2</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>(A, T, L, I, S, I, N, T, H)</th>\n",
       "      <th>syfpeithi</th>\n",
       "      <td>15</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>(H, I, S, L, A, N, G, H, D)</th>\n",
       "      <th>syfpeithi</th>\n",
       "      <td>8</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>(I, N, T, H, I, S, L, A, N)</th>\n",
       "      <th>syfpeithi</th>\n",
       "      <td>3</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>(I, S, I, N, T, H, I, S, L)</th>\n",
       "      <th>syfpeithi</th>\n",
       "      <td>16</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                       A*02:01  B*15:01\n",
       "Seq                         Method                     \n",
       "(A, N, G, H, D, A, K, A, K) syfpeithi        2        2\n",
       "(A, T, L, I, S, I, N, T, H) syfpeithi       15        2\n",
       "(H, I, S, L, A, N, G, H, D) syfpeithi        8        6\n",
       "(I, N, T, H, I, S, L, A, N) syfpeithi        3        3\n",
       "(I, S, I, N, T, H, I, S, L) syfpeithi       16        2"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "predictor = EpitopePredictorFactory(\"Syfpeithi\", version=\"1.0\")\n",
    "results = predictor.predict(peptides2, alleles=alleles, options=\"-s -b\") \n",
    "results.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h2> Chapter 2: Data manipulation and consensus prediction</h2>\n",
    "<br/>\n",
    "The predictor all return a data table like object (DataFrame) storing the peptide and allele objects, as well as the predicted results. Because it is a inherited pandas DataFrame we can do all sorts of nifty thinks. \n",
    "\n",
    "For example exporting the results to csv:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "results.to_csv('./data/test.csv', sep='\\t')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Or we could plot the score distribution of a particular HLA allele."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[<matplotlib.axes._subplots.AxesSubplot object at 0x10e76f410>,\n",
       "        <matplotlib.axes._subplots.AxesSubplot object at 0x10ea07b90>]], dtype=object)"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\nOy3QTK03GU176jnTyU7LnnodOumkGtDypG6MMaYbe+pJ2+RX35769LCnXmML9tTtqRtjjBlMy5N6\npwWaqfUmo2lPPWc62WnZU69DJ51UA1qe1I0xxnRjTz1pm/zq21OfHvbUa2zBnro9dWOMMYNpeVLv\ntEAztd5kNO2p50wnOy176nXopJNqQMuTujHGmG7sqSdtk199e+rTw556jS3YU7enbowxZjAtT+qd\nFmim1puMpj31nOlkp2VPvQ6ddFINaHlSN2Z6SLpM0h5J26cdizEL2FNP2ia/+vbUJ4ekU4EHgCsH\nPL/XnnrVFuyp21M3Jhci4gbgvmnHYUw3tZK6pNMl3Sbp25Le2Gf9nKR9kraVr7emD7UfnRZoptab\njKY99ZzpZKdlT70OnXRSDah8RqmkVcD7gBcD3wW+KunaiNjZU/ULEXHmBGI0prVIuhzYVRb3AvMR\n0SnLJ8FDqxZrLyye6yl3r/9WT7lf/WHl+Qb1iyS3EO9Cwktdbv55FmOru73CGqmHdMDpOK3J51mM\ncSHe+ZE+T1elDXVjXqJT5alL+nfA2yPi9LL8JoCIeHdPML8VES8fomNPfQr17alPFkkbgOvsqY/G\ncnnqy9FX2+SpHwPc2VXeXS7rJoBTJN0s6XpJJ9QNwBhjTDrqJPU6/3puAtZHxLOAPwGuGSuq2nRa\noJlabzKa9tSbI+nDwJeA4yTdKek1k9lSJzutleqp57ivm1LpqVP46Ou7yuspvq0fICLu73r/SUl/\nKulxEXFvd73h/uJDq5b6UeXiIX5fU3+wnj4V5dTtx9WvV7+GH7hRUmI/tN/xqRdPKn9xkkTE2dOO\nwZhe6njqq4FvAj8LfA/4CnB294VSSWuBeyIiJJ0E/E1EbOjRsac+hfr21KeHPfUaW7CnntxTr/ym\nHhEPSzof+BSwCrg0InZK2lyuvwR4FfCrkh4GHgTOqhuAMcaYdNQapx4Rn4yIp0fEUyPiXeWyS8qE\nTkRcHBH/JiI2RsQpEfHlSQa9SKcFmqn1JqNpTz1nOtlp2VNfbq36+I5SY4xZQXjul6Rt8qtvT316\n2FOvsQV76p77xRhjzGBantQ7LdBMrTcZTXvqOdPJTsue+nJr1aflSd0YY0w39tSTtsmvvj316WFP\nvcYW7KnbUzfGGDOYlif1Tgs0U+tNRtOees50stOyp77cWvVpeVI3xhjTjT31pG3yq29PfXrYU6+x\n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\njTFmBfH/AZq23Njn6m3RAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x10c8da250>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "results.hist()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To combine prediction results we can use `merge_results` from `Fred2.Core`. In addition to the result object we want to merge, also have to specify the type of these objects (here `EpitopePredictionResult`). The function will return a merged results object of the same type."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th>A*02:01</th>\n",
       "      <th>B*15:01</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Seq</th>\n",
       "      <th>Method</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th rowspan=\"4\" valign=\"top\">(F, I, A, S, N, G, V, K, L)</th>\n",
       "      <th>bimas</th>\n",
       "      <td>13.511718</td>\n",
       "      <td>0.600000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>smm</th>\n",
       "      <td>438.641785</td>\n",
       "      <td>4315.190768</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>svmhc</th>\n",
       "      <td>-0.358894</td>\n",
       "      <td>-0.836802</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>syfpeithi</th>\n",
       "      <td>25.000000</td>\n",
       "      <td>7.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"4\" valign=\"top\">(L, L, G, A, T, C, M, F, V)</th>\n",
       "      <th>bimas</th>\n",
       "      <td>650.311200</td>\n",
       "      <td>4.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>smm</th>\n",
       "      <td>27.108782</td>\n",
       "      <td>3689.775986</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>svmhc</th>\n",
       "      <td>0.969253</td>\n",
       "      <td>-0.548826</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>syfpeithi</th>\n",
       "      <td>22.000000</td>\n",
       "      <td>10.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"4\" valign=\"top\">(S, Y, F, P, E, I, T, H, I)</th>\n",
       "      <th>bimas</th>\n",
       "      <td>0.012331</td>\n",
       "      <td>0.014400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>smm</th>\n",
       "      <td>2931.635689</td>\n",
       "      <td>7014.552984</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>svmhc</th>\n",
       "      <td>0.096541</td>\n",
       "      <td>-0.524968</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>syfpeithi</th>\n",
       "      <td>17.000000</td>\n",
       "      <td>4.000000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                           A*02:01      B*15:01\n",
       "Seq                         Method                             \n",
       "(F, I, A, S, N, G, V, K, L) bimas        13.511718     0.600000\n",
       "                            smm         438.641785  4315.190768\n",
       "                            svmhc        -0.358894    -0.836802\n",
       "                            syfpeithi    25.000000     7.000000\n",
       "(L, L, G, A, T, C, M, F, V) bimas       650.311200     4.000000\n",
       "                            smm          27.108782  3689.775986\n",
       "                            svmhc         0.969253    -0.548826\n",
       "                            syfpeithi    22.000000    10.000000\n",
       "(S, Y, F, P, E, I, T, H, I) bimas         0.012331     0.014400\n",
       "                            smm        2931.635689  7014.552984\n",
       "                            svmhc         0.096541    -0.524968\n",
       "                            syfpeithi    17.000000     4.000000"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "results = [EpitopePredictorFactory(m).predict(peptides,alleles=alleles) \n",
    "                    for m in [\"Syfpeithi\",\"BIMAS\",\"SMM\",\"SVMHC\"]]\n",
    "df = results[0].merge_results(results[1:])\n",
    "df"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "We also can filter the predicted epitopes based on their prediction values with the function `filter_result` from `Fred2.Core`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th>A*02:01</th>\n",
       "      <th>B*15:01</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Seq</th>\n",
       "      <th>Method</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th rowspan=\"4\" valign=\"top\">(L, L, G, A, T, C, M, F, V)</th>\n",
       "      <th>bimas</th>\n",
       "      <td>650.311200</td>\n",
       "      <td>4.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>smm</th>\n",
       "      <td>27.108782</td>\n",
       "      <td>3689.775986</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>svmhc</th>\n",
       "      <td>0.969253</td>\n",
       "      <td>-0.548826</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>syfpeithi</th>\n",
       "      <td>22.000000</td>\n",
       "      <td>10.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"4\" valign=\"top\">(S, Y, F, P, E, I, T, H, I)</th>\n",
       "      <th>bimas</th>\n",
       "      <td>0.012331</td>\n",
       "      <td>0.014400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>smm</th>\n",
       "      <td>2931.635689</td>\n",
       "      <td>7014.552984</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>svmhc</th>\n",
       "      <td>0.096541</td>\n",
       "      <td>-0.524968</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>syfpeithi</th>\n",
       "      <td>17.000000</td>\n",
       "      <td>4.000000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                           A*02:01      B*15:01\n",
       "Seq                         Method                             \n",
       "(L, L, G, A, T, C, M, F, V) bimas       650.311200     4.000000\n",
       "                            smm          27.108782  3689.775986\n",
       "                            svmhc         0.969253    -0.548826\n",
       "                            syfpeithi    22.000000    10.000000\n",
       "(S, Y, F, P, E, I, T, H, I) bimas         0.012331     0.014400\n",
       "                            smm        2931.635689  7014.552984\n",
       "                            svmhc         0.096541    -0.524968\n",
       "                            syfpeithi    17.000000     4.000000"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#you can either use pre-defined operators from `operator`\n",
    "from operator import ge\n",
    "#or define you own comparator function like this\n",
    "comparator = lambda a,b: a > b\n",
    "\n",
    "df.filter_result([(\"svmhc\",comparator,0.0)])\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "With that one can combine several prediction tools to form a consensus prediction method.<br/><br/>\n",
    "<h2> Chapter 3: Implementation of a new epitope prediction method </h2>\n",
    "<br/>\n",
    "Fred2 possesses a potent plugin system allowing the user to extend its capability quite easily. To include a new epitope prediction method one simply has to inherit from `Fred2.Core.AEpitopePrediction` and implement its interface. For methods calling an external prediction tool additionally have to inherit from `Fred2.Core.AExternal`. SVM based methods also define a specific interface via `Fred2.Core.ASVM`. Fred2 uses SVMlight and its python binding svmlight 0.4.\n",
    "\n",
    "If you want to be very specific and fully integrate your method in all of Fred2's capabilities please use one of the three major interfaces `APSSMEpitopePrediction`, `ASVMEpitopePrediction`, or `AExternalEpitopePrediction` from `Fred2.EpitopePrediction`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "from Fred2.EpitopePrediction import APSSMEpitopePrediction\n",
    "from Fred2.Core import EpitopePredictionResult\n",
    "import random\n",
    "import pandas\n",
    "\n",
    "class RandomEpitopePrediction(APSSMEpitopePrediction):\n",
    "    __alleles = [\"A*02:01\"]\n",
    "    __supported_length = [9]\n",
    "    __name = \"random\"\n",
    "    __version= \"1.0\"\n",
    "    \n",
    "    #the interface defines three class properties\n",
    "    @property\n",
    "    def name(self):\n",
    "        #retunrs the name of the predictor\n",
    "        return self.__name\n",
    "    \n",
    "    @property\n",
    "    def supportedAlleles(self):\n",
    "        #returns the supported alleles as strings (without the HLA prefix)\n",
    "        return self.__alleles\n",
    "    \n",
    "    @property\n",
    "    def supportedLength(self):\n",
    "        #returns the supported epitope lengths as iterable\n",
    "        return self.__supported_length\n",
    "    \n",
    "    @property\n",
    "    def version(self):\n",
    "        #returns the version of the predictor\n",
    "        return self.__version\n",
    "    \n",
    "    #the interface defines a function converting Fred2's HLA allele presentation\n",
    "    #into an internal presentation used by different methods.\n",
    "    #for this predictor we won't need it but still have to provide it!\n",
    "    #the function consumes a list of alleles and converts them into the internally used presentation\n",
    "    def convert_alleles(self, alleles):\n",
    "        #we just use the identity function\n",
    "        return alleles\n",
    "    \n",
    "    #additionally the interface defines a function `predict` \n",
    "    #that consumes a list of peptides or a single peptide and optionally a list \n",
    "    #of allele objects\n",
    "    #\n",
    "    #this method implements the complete prediction routine\n",
    "    def predict(self, peptides, alleles=None):\n",
    "        \n",
    "        #test whether one peptide or a list\n",
    "        if isinstance(peptides, basestring):\n",
    "            peptides = list(peptides)\n",
    "        \n",
    "        #if no alleles are specified do predictions for all supported alleles\n",
    "        if alleles is None:\n",
    "            alleles = self.supportedAlleles\n",
    "        else:\n",
    "            #filter for supported alleles\n",
    "            alleles = filter(lambda a: a.name in self.supportedAlleles, alleles) \n",
    "        \n",
    "        result = {}\n",
    "        #now predict binding/non-binding for each peptide at random\n",
    "        for a in alleles:\n",
    "            result[a] = {}\n",
    "            for p in peptides:\n",
    "                if random.random() >= 0.5:\n",
    "                    result[a][p] = 1.0\n",
    "                else:\n",
    "                    result[a][p] = 0.0\n",
    "        \n",
    "        #create EpitopePredictionResult object. This is a multi-indexed DataFrame \n",
    "        #with Peptide and Method as multi-index and alleles as columns\n",
    "        df_result = EpitopePredictionResult.from_dict(result)\n",
    "        df_result.index = pandas.MultiIndex.from_tuples([tuple((i,self.name)) for i in df_result.index],\n",
    "                                                        names=['Seq','Method'])\n",
    "        return df_result\n",
    "            \n",
    "    \n",
    "    \n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now lets use our new predictor."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th>A*02:01</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Seq</th>\n",
       "      <th>Method</th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>(F, I, A, S, N, G, V, K, L)</th>\n",
       "      <th>random</th>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>(L, L, G, A, T, C, M, F, V)</th>\n",
       "      <th>random</th>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>(S, Y, F, P, E, I, T, H, I)</th>\n",
       "      <th>random</th>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                    A*02:01\n",
       "Seq                         Method         \n",
       "(F, I, A, S, N, G, V, K, L) random        1\n",
       "(L, L, G, A, T, C, M, F, V) random        0\n",
       "(S, Y, F, P, E, I, T, H, I) random        0"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "EpitopePredictorFactory(\"random\").predict(peptides)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The predictor is now fully integrated and can be used in any context defined by Fred2."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
